﻿using System;
using System.Collections.Generic;
using System.IO;
using EmbeddedSharp.Core;

namespace Zove.Runtime.Core.Zoom {
    /// <summary>
    /// Finds the designated file of the given class.
    /// </summary>
    public class ZoomClassFinder : IClassFinder {

        /// <summary>
        /// Extension is .zoom
        /// </summary>
        public const string ExtensionModel = ".zoom";

        protected List<string> Workspaces = new List<string>();

        /// <summary>
        /// constructor
        /// </summary>
        public ZoomClassFinder() {
            string[] s = Utils.ModelPath.Split(';');
            Workspaces.AddRange(s);
        }

        /// <summary>
        /// constructor with the workspace
        /// </summary>
        /// <param name="workspace"></param>
        public ZoomClassFinder(string workspace)
            : this() {
            string[] s = workspace.Split(';');
            Workspaces.AddRange(s);
        }

        #region IClassFinder Members

        /// <summary>
        /// add workspace to class finder
        /// </summary>
        /// <param name="workspace"></param>
        public void AddClassPath(string workspace) {
            Workspaces.Add(workspace);
        }

        /// <summary>
        /// get all class paths
        /// </summary>
        /// <returns>all class paths</returns>
        public string[] ClassPaths {
            get{
                return Workspaces.ToArray();
            }
        }

        /// <summary>
        /// Gets the location of the class.
        /// </summary>
        /// <param name="className">the class name</param>
        /// <returns>the file location</returns>
        public string GetLocation(string className) {
            string fileName = className + ExtensionModel;
            if (File.Exists(fileName)) {
                return fileName;
            }

            if (string.IsNullOrEmpty(Utils.ModelPath)) {
                throw new FileNotFoundException(fileName);
            }

            foreach (string cp in Workspaces) {
                var di = new DirectoryInfo(cp);
                string fullFileName = Find(di, fileName);

                if (!string.IsNullOrEmpty(fullFileName)) {
                    return fullFileName;
                }
            }

            return string.Empty;
        }

        /// <summary>
        /// Get the class source
        /// </summary>
        /// <param name="className"></param>
        /// <returns></returns>
        public string GetSource(string className) {
            string location = GetLocation(className);

            return File.ReadAllText(location);
        }

        #endregion

        /// <summary>
        /// Iteratively finds class over directories;
        /// </summary>
        /// <param name="di"></param>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public string Find(DirectoryInfo di, string fileName) {
            if (di.Name == ".svn") {
                return string.Empty;
            }

            foreach (FileInfo fi in di.GetFiles()) {
                if (string.Compare(
                    fi.Name, fileName, StringComparison.CurrentCultureIgnoreCase) == 0) {
                    return fi.FullName;
                }
            }

            foreach (DirectoryInfo sdi in di.GetDirectories()) {
                string found = Find(sdi, fileName);
                if (!string.IsNullOrEmpty(found)) {
                    return found;
                }
            }

            return string.Empty;
        }
    }
}